#ifndef _UI_MANAGER_H_
#define _UI_MANAGER_H_

#include "input/keyboard.h"
#include "input/mouse.h"

#include "ui_widget.h"
#include "math/counter.h"

namespace LuaPlus
{
    class LuaObject;
    class LuaState;
};

// I don't need this in other platforms yet
#if defined(_PLATFORM_ANDROID) || defined(_PLATFORM_IOS)
#else
	
namespace flash
{
	class FlashDriver;
	class FlashMovie;
}

#endif


namespace camera
{
	class AbstractCamera;
}

namespace ui
{
class UIText;
class UIWidget;
class UIManager : 
		input::KeyboardListener, 
		input::MouseListener 
{	
public:
    static UIManager&	Instance();
	
	
                        UIManager();		// must be public to keep LuaBind happy
                       ~UIManager();		// must be public to keep LuaBind happy
	void				Shutdown();
	void				Render();
	void				Tick(float dt);
	void				SetFocus(UIWidget* pWidget);
	void				SetEditWidget(UIWidget* pText);
	void				ClearEditWidget();
	UIWidget*			GetFocus() const { return m_pFocus; };
	void				SetSelected(UIWidget* pWidget) { m_pSelected  = pWidget; };
	UIWidget*			GetSelected() const { return m_pSelected; };
	UIText*				GetEditText() const { return m_pEditWidget; };

	bool				IsShowCursor() const { return m_ShowCursor; };
	void				SetShowCursor(bool b) { m_ShowCursor = b; };
	void				SetCursor(const std::string& File, const math::Vec2& Size, const math::Vec2& Offset); 
	void				SetDragTarget(UIWidget* pWidget);
	UIWidget*			GetDragTarget() const { return m_pDragTarget; };
	bool				HasActiveAnimation();

	/// mouse events
	virtual	void		MouseButtonPressed(input::Mouse::BUTTON_STATE* pKey, const math::Vec2& Pos);
	virtual	void		MouseButtonDblClick(input::Mouse::BUTTON_STATE* pKey, const math::Vec2& Pos);
	virtual void		MouseButtonReleased(input::Mouse::BUTTON_STATE* pKey, const math::Vec2& Pos);
	virtual void		MouseButtonDown(input::Mouse::BUTTON_STATE* pKey, const math::Vec2& Pos);
	virtual void		MouseButtonRepeat(input::Mouse::BUTTON_STATE* pKey, const math::Vec2& Pos);
	virtual void		MouseWheelMove(int WheelInfo, const math::Vec2& Pos);
	virtual void		MouseHoover(const math::Vec2& Pos);
	virtual void		MouseMove(const math::Vec2& From, const math::Vec2& To);
	virtual void		MouseOnDrag(const math::Vec2& From, const math::Vec2& To);
	virtual void		MouseOnDrop(const math::Vec2& From, const math::Vec2& To);
	bool				MouseInside(const math::Vec2& Pos);
	bool				MouseInsideActive(const math::Vec2& Pos);

	/// keyboard event
	virtual	void		KeyPressed(input::Keyboard::KEY* pKey);
	virtual void		KeyReleased(input::Keyboard::KEY* pKey);
	virtual void		KeyDown(input::Keyboard::KEY* pKey);
	virtual void		KeyRepeat(input::Keyboard::KEY* pKey);
	virtual void		CharReceived(unsigned int Key);

	// Execute a script
	void				ExecuteScript(const std::string& Script);
	
	// force reload of all active panels..note, since this is actually a destroy operation
	// it will invalidate any pointers you're hanging on to.
	void				RefreshActive();
	void				RefreshFonts();

	// panel manipulation
	UIWidget*			AddPanel(const std::string& File);
	void				SavePanel(UIWidget* pPanel, const std::string& File);
	UIWidget*			AddEmptyPanel(const std::string& Name);
	void				AddWidget(UIWidget* pPanel);
	bool				PanelExists(UIWidget* pPanel);
	UIWidget*			GetPanel(const std::string& Name);
	bool				DropWidget(UIWidget* pWidget);
	bool				DropPanel(UIWidget* pPanel, bool Delete = true);
	bool				DropAllPanels();
	UIWidget*			GetWidget(const std::string& Name);
	void				PushPanelToFront(UIWidget* pPanel);
	void				PushPanelToBack(UIWidget* pPanel);

	static	UIWidget*	CreateWidget(UIWidget* pParent, LuaPlus::LuaObject _LObj);
	static	UIWidget*	CreateWidget(UIWidget* pParent, const std::string& Type);

	// refresh the strings, for use when we change language
	void				RefreshText();

	const std::string&	GetDefaultFont()const { return m_DefaultFont; };
	void				SetDefaultFont(const std::string& s) { m_DefaultFont = s; };
	void				ForceLeftAlign(bool b);
	static	void		Register(LuaPlus::LuaState* _pScript);
	void				SetSelectedDropDown(UIDropDown* pW) { m_pSelectedDropDown = pW; };
	UIDropDown*			GetSelectedDropDown() const  { return m_pSelectedDropDown ; };

	void				InitFlash();
	void				ShutdownFlash();

// I don't need this in other platforms yet
#if defined(_PLATFORM_ANDROID) || defined(_PLATFORM_IOS)
#else
	
	flash::FlashDriver*	GetFlash() { return m_pFlashPlayer; };

#endif

	
	void				EnableFlash() { m_FlashEnabled = true; }

	void				ResetResources();
	void				SetCamera(camera::AbstractCamera*	pCam) { m_pCamera = pCam; };
	camera::AbstractCamera*		GetCamera() const { return m_pCamera; };

	void				SetLocalization(const std::string& text) { m_Localization = text; };
	const std::string&	GetLocalization() const { return m_Localization;};
	void				UpdateLocalization();
	
	void				AddReplaceWord(const std::string& From, const std::string& To);

	void				EnableInput(bool b);
	void				SetVisible(bool b) { m_IsVisible = b; };
	bool				IsVisible() const { return m_IsVisible; };

// eternal text object registration
	void				RegisterExternalText(UIText* pTextObj);
	void				DeRegisterExternalText(UIText* pTextObj);

	//tips methods
	void				SetCurTipID(const std::string& NewTipID) {m_CurTipID = NewTipID;};
	void				TickTips(float dt);

	int					GetVisiblePanels() const { return m_VisiblePanels; };
	int					GetVisibleWidgets() const { return m_VisibleWidgets; };
	void				WidgetRendered() { m_VisibleWidgets++; };


	typedef	void (*SpriteLoadedCB)(void* pData);
	void				SetLoadCB(SpriteLoadedCB pCB, void* pData) { m_LoadCallback = pCB; m_pLoadCBData = pData; };
	void				UpdateLoadCB() { 	if (m_LoadCallback)m_LoadCallback(m_pLoadCBData); };
	
	void				FlushSprites();
	
private:
	SpriteLoadedCB		m_LoadCallback;
	void*				m_pLoadCBData;

    /// Not implemented to prevent copying
    UIManager( const UIManager & );     
    UIManager& operator=( const UIManager & );

	/// widget currently in focus
	UIWidget*			m_pFocus;
	UIWidget*			m_pSelected;
	UIDropDown*			m_pSelectedDropDown;
	UIWidget*			m_pDragTarget;

	/// panels attached
	std::vector<UIWidget*>	m_Panels;
	bool					m_IsVisible;

	// tips panel - being hold in separate pointer
	UIWidget*				m_pTipsPanel;
	UIWidget*				m_pCurTip;
	std::string				m_CurTipID;
	math::Counter			m_TipCounter;

	 static const int		TIPDELAY = 0;

	// external text objects list
	std::vector<UIText*>	m_ExtTextObjs;

	/// mouse pointer
	bool				m_ShowCursor;
	UISprite			m_Pointer;
	math::Vec2			m_MousePos;
	math::Vec2			m_MouseSize;
	math::Vec2			m_MouseOffset;
	math::Vec2			m_DragFrom;

	/// defaults
	std::string			m_DefaultFont;
	std::string			m_Localization;

	UIText*				m_pEditWidget;


// I don't need this in other platforms yet
#if defined(_PLATFORM_ANDROID) || defined(_PLATFORM_IOS)
#else
	
	// flash driver
	flash::FlashDriver*			m_pFlashPlayer;

#endif

	bool				m_FlashEnabled;

	// particle camera
	camera::AbstractCamera*		m_pCamera;

	int					m_VisiblePanels;
	int					m_VisibleWidgets;

	
};

}  // namespace ui
#define UIMAN() ui::UIManager::Instance()

#endif // _UI_MANAGER_H_